package top.codestudy.recordescreen.services;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.RemoteViews;

import java.io.File;
import java.io.IOException;

import top.codestudy.recordescreen.R;
import top.codestudy.recordescreen.commons.ToastUtil;

import static android.os.Environment.getExternalStoragePublicDirectory;

public class RecorderService extends Service {
    private String TAG = getClass().getSimpleName();
    private MediaProjection mediaProjection;
    private MediaRecorder mediaRecorder;
    private DisplayMetrics dm;
    private VirtualDisplay virtualDisplay;

    private boolean isMediaRecorderPrepare = false;

    public RecorderService() {
    }

    public void init() {
        isMediaRecorderPrepare = false;
        virtualDisplay = null;
        mediaRecorder = null;
        mediaProjection = null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init();
        dm = getResources().getDisplayMetrics();
        startForegroundService();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new RecorderServiceBinder();
    }

    /**
     * 1.开始录制
     * 2.停止录制
     */
    public void startRecorder(MediaProjection mediaProjection) {
        if (mediaProjection == null) {
            Log.i(TAG, "startRecorder: But mediaProjection == null !!!");
            return;
        }

        this.mediaProjection = mediaProjection;
        mediaRecorder = new MediaRecorder();
        initMediaRecorder();
        if (isMediaRecorderPrepare) {
            createVirtualDisplay();
            mediaRecorder.start();
            Log.i(TAG, "startRecorder: ok!");
        }
    }

    private void initMediaRecorder() {
        File file = new File(getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "Recorder-" + System.currentTimeMillis() + ".mp4");
        Log.i(TAG, "initMediaRecorder: file ==> " + file.getAbsolutePath());
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mediaRecorder.setOutputFile(file.getAbsolutePath());
        mediaRecorder.setVideoSize(dm.widthPixels, dm.heightPixels);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
        mediaRecorder.setVideoFrameRate(60);
        try {
            mediaRecorder.prepare();
            isMediaRecorderPrepare = true;
        } catch (IOException e) {
            isMediaRecorderPrepare = false;
            e.printStackTrace();
        }
    }

    private void createVirtualDisplay() {
        virtualDisplay = mediaProjection.createVirtualDisplay(
                "MainScreen",
                dm.widthPixels,
                dm.heightPixels,
                dm.densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mediaRecorder.getSurface(),
                null, null);
    }

    public void stopRecorder() {
        if (mediaRecorder != null){
            mediaRecorder.stop();
            mediaRecorder.release();
        }

        if (virtualDisplay != null){
            virtualDisplay.release();
        }
        if (mediaProjection != null){
            mediaProjection.stop();
        }
        init();
    }


    public void setMediaProjection(MediaProjection mediaProjection) {
        this.mediaProjection = mediaProjection;
    }

    private void startForegroundService() {
        RemoteViews normalView = new RemoteViews(getPackageName(), R.layout.item_recorder_notification);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            String id = "id";
            CharSequence name = "RecorderService";
            int importance = NotificationManager.IMPORTANCE_LOW;
            NotificationChannel channel = new NotificationChannel(id, name, importance);
            mNotificationManager.createNotificationChannel(channel);

            Notification notification = new Notification.Builder(this, "id")
                    .setContentTitle("RecorderService")
                    .setContentText("RecorderService")
                    .setOngoing(true)
                    .setSmallIcon(android.R.drawable.sym_def_app_icon)
                    .build();
            startForeground(1, notification);
        } else {
            Notification notification = new Notification.Builder(this)
                    .setSmallIcon(android.R.drawable.sym_def_app_icon)
                    .setContentTitle("RecorderService")
                    .setContentText("RecorderService")
                    .setOngoing(true)
                    .build();
            startForeground(1, notification);
        }
    }

    private void closeNotification(){
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(1);
        ToastUtil.shortShow(this,"停止录制");
    }

    public class RecorderServiceBinder extends Binder {

        public RecorderService getRecorderService() {
            return RecorderService.this;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopRecorder();
        closeNotification();
    }
}
